import axios from 'axios';
import { ElMessage } from 'element-plus';
import { useUserStore } from '../store/user';
import router from '@/router';

// 定义请求配置接口
interface RequestConfig extends Record<string, any> {
  showLoading?: boolean;
  showError?: boolean;
  returnRaw?: boolean;
  useI18n?: boolean; // 是否使用国际化请求头
}

// 定义API响应接口
interface ApiResponse<T = any> {
  rows?:any;
  total: number;
  statusCode: number;
  code: number;
  data: T;
  message: string;
  type?: number;
}

// 业务状态码
const BusinessCode = {
  SUCCESS: 200,
  NOT_LOGIN: 401
} as const;

// HTTP状态码
const HttpStatus = {
  OK: 200,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  INTERNAL_SERVER_ERROR: 500
} as const;

// 创建 axios 实例
const instance = axios.create({
  baseURL:  '/api',
  timeout: 15000,
  headers: {
    'Content-Type': 'application/json'
  }
});

// 存储请求队列，用于取消重复请求
const pendingRequests = new Map();

// 生成请求的唯一标识
const generateRequestKey = (config: any) => {
  const { url, method, params, data } = config;
  return [url, method, JSON.stringify(params), JSON.stringify(data)].join('&');
};

// 添加请求到队列
const addPendingRequest = (config: any) => {
  const requestKey = generateRequestKey(config);
  if (!pendingRequests.has(requestKey)) {
    const controller = new AbortController();
    config.signal = controller.signal;
    pendingRequests.set(requestKey, controller);
  } else {
    // 取消重复请求
    const controller = pendingRequests.get(requestKey);
    controller.abort();
    pendingRequests.delete(requestKey);
    
    // 创建新的控制器
    const newController = new AbortController();
    config.signal = newController.signal;
    pendingRequests.set(requestKey, newController);
  }
};

// 从队列中移除请求
const removePendingRequest = (config: any) => {
  const requestKey = generateRequestKey(config);
  if (pendingRequests.has(requestKey)) {
    pendingRequests.delete(requestKey);
  }
};

// 清除所有请求
const clearPendingRequests = () => {
  pendingRequests.forEach((controller) => {
    controller.abort();
  });
  pendingRequests.clear();
};

// 获取token
const getToken = () => {
  const userStore = useUserStore();
  console.log(userStore,'useUserStore.token');
  return userStore.token;
};

// 移除token
const removeToken = () => {
  const userStore = useUserStore();
  userStore.clearLoginState();
};

// 全局loading计数器
let loadingCount = 0;
let loadingInstance: any = null;

// 显示全局loading
const showLoading = () => {
  loadingCount++;
  if (loadingCount === 1) {
    // 这里可以实现全局loading，例如使用Element Plus的loading服务
    // loadingInstance = ElLoading.service({
    //   fullscreen: true,
    //   text: '加载中...'
    // });
  }
};

// 隐藏全局loading
const hideLoading = () => {
  loadingCount--;
  if (loadingCount === 0 && loadingInstance) {
    // loadingInstance.close();
    loadingInstance = null;
  }
};

// 消息提示
const message = {
  info: (content: string) => ElMessage.info(content),
  success: (content: string) => ElMessage.success(content),
  warning: (content: string) => ElMessage.warning(content),
  error: (content: string) => ElMessage.error(content)
};

// 获取当前语言
const getCurrentLanguage = () => {
  // 从localStorage获取当前语言设置，默认为中文
  return localStorage.getItem('language') || 'zh';
};

// 请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 移除重复请求
    removePendingRequest(config);
    // 添加请求到队列
    addPendingRequest(config);
    
    // 添加token到请求头
    const token = getToken();
    console.log(token,'token---');
    
    // 初始化headers对象
    config.headers = {
      ...(config.headers as Record<string, any>)
    } as any;
    
    if (token) {
      // 添加token到请求头
      config.headers.token = token;
    }
    
    // 添加国际化请求头，默认添加，除非明确设置useI18n为false
    if ((config as any).useI18n !== false) {
      const language = getCurrentLanguage();
      config.headers['Accept-Language'] = language;
    }
    
    // 显示全局loading
    if ((config as any).showLoading !== false) {
      showLoading();
    }
    
    return config;
  },
  (error) => {
    hideLoading();
    // 显示网络连接错误提示
    message.error('网络连接错误');
    return Promise.reject(error);
  }
);

// 响应拦截器
instance.interceptors.response.use(
  (response) => {
    // 移除请求队列中的请求
    removePendingRequest(response.config);
    
    // 隐藏全局loading
    if ((response.config as any).showLoading !== false) {
      hideLoading();
    }
    
    const res = response.data;
    
    // 如果是下载文件，直接返回
    if (response.config.responseType === 'blob') {
      return response;
    }
    
    // 如果返回的是原始响应，不进行处理
    if ((response.config as any).returnRaw) {
      return response;
    }
    
    // 根据type类型处理不同的响应
    if (res.type !== undefined) {
      switch (res.type) {
        case 1:
          // 提示信息
          message.info(res.message || '操作提示');
          break;
        case 2:
          // 成功提示
          message.success(res.message || '操作成功');
          break;
        case 3:
          // 警告信息
          message.warning(res.message || '操作警告');
          break;
        case 4:
          // 失败提示信息
          message.error(res.message || '操作失败');
          break;
        case 5:
          // 注意提示并清除登录状态
          message.warning(res.message || '登录已过期，请重新登录');
          // 清除token和用户信息
          const userStore = useUserStore();
          // 使用store.commit设置token和用户信息为null
          // userStore.setToken(null);
          userStore.setCurrentUser(null);
          // 跳转到首页
          router.replace('/');
          return Promise.reject(new Error(res.message || '登录已过期'));
        default:
          break;
      }
    }
    if(res.statusCode === 4202){
      message.warning(res.message || '操作警告');
    }
    
    // 处理业务状态码 ||  code === 0
    if (res.code !== BusinessCode.SUCCESS && res.code !== 0) {
      // 未登录或token过期
      if (res.code === BusinessCode.NOT_LOGIN) {
        // 清除token
        removeToken();
        // 跳转到登录页
        window.location.href = `/login?redirect=${encodeURIComponent(window.location.pathname)}`;
        return Promise.reject(new Error(res.message || '未登录或登录已过期'));
      }
      
      // 显示错误信息
      // if (response.config.showError !== false && res.type === undefined) {
      //   message.error(res.message || '请求失败');
      // }
      
      return Promise.reject(new Error(res.message || '请求失败'));
    }
    
    return res;
  },
  (error) => {
    // 如果请求被取消，不显示错误
    if (axios.isCancel(error)) {
      return Promise.reject(error);
    }
    
    // 隐藏全局loading
    hideLoading();
    
    // 移除请求队列中的请求
    if (error.config) {
      removePendingRequest(error.config);
    }
    
    // 处理Network Error错误
    if (error.message === 'Network Error') {
      message.error('网络连接中断(Network Error)');
      return Promise.reject(error);
    }
    
    // 处理HTTP状态码
    if (error.response) {
      const { status } = error.response;
      
      // 未授权
      if (status === HttpStatus.UNAUTHORIZED) {
        // 清除token
        removeToken();
        // 跳转到登录页
        window.location.href = `/login?redirect=${encodeURIComponent(window.location.pathname)}`;
        return Promise.reject(new Error('未登录或登录已过期'));
      }
      
      // 显示错误信息
      if ((error.config as any)?.showError !== false) {
        switch (status) {
          case HttpStatus.BAD_REQUEST:
            message.error('请求参数错误');
            break;
          case HttpStatus.FORBIDDEN:
            message.error('没有权限访问');
            break;
          case HttpStatus.NOT_FOUND:
            message.error('请求的资源不存在');
            break;
          case HttpStatus.INTERNAL_SERVER_ERROR:
            message.error('服务器内部错误');
            break;
          default:
            message.error(`请求失败(${status})`);
        }
      }
    } else {
      // 其他网络错误或请求被取消
      if ((error.config as any)?.showError !== false && error.message !== 'Network Error') {
        message.error('网络错误，请检查您的网络连接');
      }
    }
    
    return Promise.reject(error);
  }
);

/**
 * 发送请求
 * @param config 请求配置
 * @returns Promise
 */
const request = async <T = any>(config: RequestConfig): Promise<ApiResponse<T>> => {
  try {
    const { url, method = 'GET', params, data, headers, useI18n = true, ...rest } = config;

    const fullUrl = `${import.meta.env.VITE_API_BASE_URL}${url.startsWith('/') ? url : `/${url}`}`;

    const axiosConfig = {
      url: fullUrl,
      method,
      params,
      data,
      headers,
      useI18n,
      ...rest
    };

    const response = await instance.request(axiosConfig);
    return response as unknown as ApiResponse<T>;
  } catch (error) {
    return Promise.reject(error);
  }
};

/**
 * GET请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 请求配置
 * @returns Promise
 */
const get = <T = any>(
  url: string,
  params?: Record<string, any>,
  config?: Omit<RequestConfig, 'url' | 'method' | 'params'>
): Promise<ApiResponse<T>> => {
  return request<T>({
    url,
    method: 'GET',
    params,
    ...config
  });
};

/**
 * POST请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise
 */
const post = <T = any>(
  url: string,
  data?: any,
  config?: Omit<RequestConfig, 'url' | 'method' | 'data'>
): Promise<ApiResponse<T>> => {
  return request<T>({
    url,
    method: 'POST',
    data,
    ...config
  });
};

/**
 * PUT请求
 * @param url 请求地址
 * @param data 请求数据
 * @param config 请求配置
 * @returns Promise
 */
const put = <T = any>(
  url: string,
  data?: any,
  config?: Omit<RequestConfig, 'url' | 'method' | 'data'>
): Promise<ApiResponse<T>> => {
  return request<T>({
    url,
    method: 'PUT',
    data,
    ...config
  });
};

/**
 * DELETE请求
 * @param url 请求地址
 * @param params 请求参数
 * @param config 请求配置
 * @returns Promise
 */
const del = <T = any>(
  url: string,
  params?: Record<string, any>,
  config?: Omit<RequestConfig, 'url' | 'method' | 'params'>
): Promise<ApiResponse<T>> => {
  return request<T>({
    url,
    method: 'DELETE',
    params,
    ...config
  });
};

/**
 * 上传文件
 * @param url 上传地址
 * @param file 文件对象
 * @param name 文件字段名
 * @param data 其他表单数据
 * @param config 请求配置
 * @returns Promise
 */
const uploadFile = <T = any>(
  url: string,
  file: File,
  name = 'file',
  data?: Record<string, any>,
  config?: Omit<RequestConfig, 'url' | 'method' | 'data' | 'headers'>
): Promise<ApiResponse<T>> => {
  const formData = new FormData();
  formData.append(name, file);
  
  if (data) {
    Object.keys(data).forEach(key => {
      formData.append(key, data[key]);
    });
  }
  
  return request<T>({
    url,
    method: 'POST',
    data: formData,
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    ...config
  });
};

/**
 * 下载文件
 * @param url 下载地址
 * @param params 请求参数
 * @param filename 文件名
 * @param config 请求配置
 * @returns Promise
 */
const downloadFile = async (
  url: string,
  params?: Record<string, any>,
  filename?: string,
  config?: Omit<RequestConfig, 'url' | 'method' | 'params' | 'responseType'>
): Promise<Blob> => {
  try {
    const response = await instance.request({
      url,
      method: 'GET',
      params,
      responseType: 'blob',
      ...config
    });
    
    const blob = new Blob([response.data]);
    
    // 获取文件名
    let downloadFilename = filename;
    if (!downloadFilename) {
      const disposition = response.headers['content-disposition'];
      if (disposition) {
        const filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
        const matches = filenameRegex.exec(disposition);
        if (matches != null && matches[1]) {
          downloadFilename = matches[1].replace(/['"]/g, '');
        }
      }
    }
    
    // 创建下载链接
    const link = document.createElement('a');
    link.href = URL.createObjectURL(blob);
    link.download = downloadFilename || 'download';
    link.style.display = 'none';
    document.body.appendChild(link);
    link.click();
    URL.revokeObjectURL(link.href);
    document.body.removeChild(link);
    
    return blob;
  } catch (error) {
    return Promise.reject(error);
  }
};

// 导出所有方法
export {
  request,
  get,
  post,
  put,
  del as delete,
  uploadFile,
  downloadFile,
  clearPendingRequests
};

// 为了兼容性，我们需要修改request函数，使其既可以作为函数调用，也可以作为对象使用
const requestWithMethods = Object.assign(request, {
  request,
  get,
  post,
  put,
  delete: del,
  uploadFile,
  downloadFile,
  clearPendingRequests
});

// 默认导出增强后的request函数
export default requestWithMethods;